﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data.OleDb;
using System.Data;
using System.Text.RegularExpressions;
using umbraco.cms;
using umbraco.uicontrols;
using System.Collections;
using umbraco.IO;
using System.IO;

namespace Our.Umbraco.uDbCompare
{
    public partial class info : System.Web.UI.Page
    {
        public TabPage infoTab;
        public TabPage localTab;
        public TabPage inUseTab;

        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);

            infoTab = TabViewDetails.NewTabPage("uDbCompare Info");
            infoTab.Controls.Add(InfoPanel);

            inUseTab = TabViewDetails.NewTabPage("In Use");
            inUseTab.Controls.Add(InUsePanel);

            localTab = TabViewDetails.NewTabPage("Local Actions");
            localTab.Controls.Add(LocalPanel);

        }

        protected void Page_Load(object sender, EventArgs e)
        {
            if (!Page.IsPostBack)
                BindData();    
        }

        public void BindData()
        {
            populateXsltFiles();

            if (SessionVars.IsValidDbConnection(false))
            {
                SearchButton.Enabled = true;
            }
        }

        #region Button Events

        protected void SyncTemplateButton_OnClick(object sender, EventArgs e)
        {
            SyncTemplates();
        }

        protected void SearchButton_OnClick(object sender, EventArgs e)
        {
            DataTable matchDt = FindXslt(xsltFiles.SelectedValue);
            XsltGridView.DataSource = matchDt;
            XsltGridView.DataBind();

            NoResultsLabel.Visible = (matchDt.Rows.Count == 0);
        }

        protected void SearchAllButton_OnClick(object sender, EventArgs e)
        {
            DataTable matchDt = new DataTable();
            
            matchDt.Columns.Add("Xslt", typeof(string));
            matchDt.Columns.Add("Macro", typeof(string));

            foreach(ListItem listItem in xsltFiles.Items)
            {
                var dt = FindXslt(listItem.Text);
                DataRow dr = matchDt.NewRow();
                dr["Xslt"] = listItem.Text;
                if (dt.Rows.Count > 0)
                    dr["Macro"] = dt.Rows[0][0].ToString();
                
                matchDt.Rows.Add(dr);
            }

            XsltGridView.DataSource = matchDt;
            XsltGridView.DataBind();

            NoResultsLabel.Visible = (matchDt.Rows.Count == 0);
        }

        protected void OrphanTemplateButton_OnClick(object sender, EventArgs e)
        {
            ArrayList masterPages = getMasterPageFiles();
            var templates = global::umbraco.cms.businesslogic.template.Template.GetAllAsList();

            DataTable dt = new DataTable();
            dt.Columns.Add("MasterPage File");
            dt.Columns.Add("Template Exists");
            dt.Columns.Add("Db Data Match");
            dt.Columns.Add("Db Parent Match");
            dt.Columns.Add("MasterPage Parent File");
            dt.Columns.Add("Template Parent Alias");
            foreach (var file in masterPages)
            {
                DataRow dr = dt.NewRow();
                dr["MasterPage File"] = file.ToString();

                string fileContent = GetMasterPageContent(file.ToString());
                string parentFileMasterPage = GetParentMasterPageFromContent(fileContent); 

                var template = templates.Where(x => x.Alias.Replace(" ", "") == file.ToString().Replace(".master", "")).FirstOrDefault();
                if (template == null)
                {
                    dr["Template Exists"] = "Missing!";
                }
                else
                {
                    if (fileContent.Replace(" ", "") == template.Design.Replace(" ", ""))
                    {
                        dr["Db Data Match"] = "Yes";
                    }
                    else
                    {
                        dr["Db Data Match"] = "No";
                    }

                    var parentTemplate = templates.Where(x => x.Id == template.MasterTemplate).FirstOrDefault();
                    if (parentTemplate != null)
                    {
                        dr["Template Parent Alias"] = parentTemplate.Alias;
                        if (parentFileMasterPage.Replace(".master", "") == parentTemplate.Alias.Replace(" ", ""))
                            dr["Db Parent Match"] = "Yes";
                        else
                            dr["Db Parent Match"] = "No";
                    }
                }

                dr["MasterPage Parent File"] = parentFileMasterPage;


                dt.Rows.Add(dr);
            }

            OrphanTemplateGridView.DataSource = dt;
            OrphanTemplateGridView.DataBind();
        }

        #endregion

        protected void OrphanTemplateGridView_OnRowDataBound(object sender, GridViewRowEventArgs e)
        {
            if (e.Row.RowType == DataControlRowType.DataRow)
            {
                foreach (TableCell cell in e.Row.Cells)
                {
                    if (cell.Text == "Missing!" || cell.Text == "No")
                        cell.BackColor = System.Drawing.Color.Red;
                }
            }
        }

        #region Xslt Methods

        private DataTable FindXslt(string xslt)
        {
            string xsltQuery = "select distinct macroAlias from cmsMacro where macroXslt = ?";
            
            OleDbParameter[] parameters = new OleDbParameter[1];
            parameters[0] = new OleDbParameter("@XsltFile", xslt);
            DataTable dt = Db.QueryDb(xsltQuery, false, parameters);

            return dt;
        }

        // Copied from umbraco.cms.presentation.developer.editMacro (shame it wasn't exposed)
        private void getXsltFilesFromDir(string orgPath, string path, ArrayList files)
        {
            DirectoryInfo dirInfo = new DirectoryInfo(path);

            // Populate subdirectories
            DirectoryInfo[] dirInfos = dirInfo.GetDirectories();
            foreach (DirectoryInfo dir in dirInfos)
            {
                // Make sure to exclude svn folder
                if (dir.Name != ".svn")
                    getXsltFilesFromDir(orgPath, path + "/" + dir.Name, files);
            }
            FileInfo[] fileInfo = dirInfo.GetFiles("*.xsl*");

            foreach (FileInfo file in fileInfo)
                files.Add((path.Replace(orgPath, string.Empty).Trim('/') + "/" + file.Name).Trim('/'));
        }

        // Copied from umbraco.cms.presentation.developer.editMacro (shame it wasn't exposed)
        private void populateXsltFiles()
        {
            ArrayList xslts = new ArrayList();
            string xsltDir = IOHelper.MapPath(SystemDirectories.Xslt + "/");
            getXsltFilesFromDir(xsltDir, xsltDir, xslts);
            xsltFiles.DataSource = xslts;
            xsltFiles.DataBind();
        }

        #endregion

        #region Template Methods

        // Modified from umbraco.cms.presentation.developer.editMacro 
        private void getMasterPageFilesFromDir(string orgPath, string path, ArrayList files)
        {
            DirectoryInfo dirInfo = new DirectoryInfo(path);

            // Populate subdirectories
            DirectoryInfo[] dirInfos = dirInfo.GetDirectories();
            foreach (DirectoryInfo dir in dirInfos)
            {
                // Make sure to exclude svn folder
                if (dir.Name != ".svn")
                    getMasterPageFilesFromDir(orgPath, path + "/" + dir.Name, files);
            }
            FileInfo[] fileInfo = dirInfo.GetFiles("*.master");

            foreach (FileInfo file in fileInfo)
                files.Add((path.Replace(orgPath, string.Empty).Trim('/') + "/" + file.Name).Trim('/'));
        }

        // Modified from umbraco.cms.presentation.developer.editMacro
        private ArrayList getMasterPageFiles()
        {
            ArrayList masterPages = new ArrayList();
            string masterPageDir = IOHelper.MapPath(SystemDirectories.Masterpages + "/");
            getMasterPageFilesFromDir(masterPageDir, masterPageDir, masterPages);
            return masterPages;
        }

        private void SyncTemplates()
        {
            var templates = global::umbraco.cms.businesslogic.template.Template.GetAllAsList();
            foreach (var template in templates)
            {
                // looks a bit silly, but the set propery does a db save
                template.Text = template.Text;
                template.Alias = template.Alias;
                template.MasterTemplate = template.MasterTemplate;
                template.Design = template.Design;

                template.Save();
            }
        }

        private string GetMasterPageContent(string filename)
        {
            string content = null;
            string masterPageDir = IOHelper.MapPath(SystemDirectories.Masterpages + "/");
            using (var reader = File.OpenText(string.Format("{0}\\{1}", masterPageDir, filename)))
            {
                content = reader.ReadToEnd();
            }
            return content;
        }

        private string GetParentMasterPageFromContent(string content)
        {
            // <%@\s*(?i)master[^>]*>
            string regex = @"<%@\s*(?i)master[^>]*>";
            Match masterMatch = Regex.Match(content, regex);
            if (masterMatch.Success)
            {
                // (?i)masterpagefile="[^"]*"
                string pageFileRegEx = String.Format(@"(?i)masterpagefile={0}([^{0}]*){0}", "\"");
                Match pageFileMatch = Regex.Match(masterMatch.Value, pageFileRegEx);
                if (pageFileMatch.Success)
                    return GetMasterPageFileName(pageFileMatch.Groups[1].Value);
            }
            return null;
        }

        private string GetMasterPageFileName(string filename)
        {
            string masterPageDir = SystemDirectories.Masterpages.Replace("~", "");
            int dirIndex = filename.IndexOf(masterPageDir);
            if (dirIndex >= 0)
            {
                return filename.Substring(dirIndex + masterPageDir.Length).Replace(@"\", "").Replace("/", "");
            }
            else
            {
                return filename;
            }
        }

        #endregion
    }
}
